#include "mainwindow_p.h"
#include "mainwindow.h"
#include <QDebug>

#include "testpage.h"
#include "curvetestpage.h"
#include "ffttestpage.h"
#include "sigslottestpage.h"

#include "messagequeue.h"
#include "modulemanager.h"
#include "module/hplc/pump/modulehplcpump.h"
#include "module/simplefoccontroller.h"
#include "simplefocprotocol.h"
#include "pageuartconfig.h"
#include "pageuart.h"
#include "portmanager.h"

#include "curve.h"
#include "hplccommontabpage.h"
#include "hplcdebuginfopage.h"
#include "hplcpumptabpage.h"
#include "hplcpumppanel.h"
#include "hplctimeprogrampage.h"
#include "hplcautosamplerbasiccontrolpage.h"
#include "hplcautosamplerbasiccontroldevicepage.h"

#include "electronicscalerealtimecurvepage.h"
#include "electronicscaledataprocesspage.h"
#include "electronicscale/lichen/moduleelectronicscalelichen.h"
#include "electronicscale/shimadzu/moduleelectronicscaleshimadzu.h"

#include "updatepage.h"
#include "ui_ymodem.h"

MainWindowPrivate::MainWindowPrivate()
    : DPtrPrivate<MainWindow>()
{

}

MainWindowPrivate::~MainWindowPrivate()
{

}

void MainWindowPrivate::createFileMenuActions_helper()
{
    DPTR_P(MainWindow);

    fileMenu = p.menuBar()->addMenu(QObject::tr("&File"));
    fileToolBar = p.addToolBar(QObject::tr("File"));

    const QIcon newIcon = QIcon::fromTheme("document-new", QIcon("./images/new.png"));
    newAct = new QAction(newIcon, QObject::tr("&New"), &p);
    newAct->setShortcuts(QKeySequence::New);
    newAct->setStatusTip(QObject::tr("Create a new file"));
    QObject::connect(newAct, &QAction::triggered, &p, &MainWindow::newFile);
    fileMenu->addAction(newAct);
    fileToolBar->addAction(newAct);

    const QIcon openIcon = QIcon::fromTheme("document-open", QIcon("./images/open.png"));
    openAct = new QAction(openIcon, QObject::tr("&Open..."), &p);
    openAct->setShortcuts(QKeySequence::Open);
    openAct->setStatusTip(QObject::tr("Open an existing file"));
    QObject::connect(openAct, &QAction::triggered, &p, &MainWindow::open);
    fileMenu->addAction(openAct);
    fileToolBar->addAction(openAct);

    const QIcon saveIcon = QIcon::fromTheme("document-save", QIcon("./images/save.png"));
    saveAct = new QAction(saveIcon, QObject::tr("&Save"), &p);
    saveAct->setShortcuts(QKeySequence::Save);
    saveAct->setStatusTip(QObject::tr("Save the document to disk"));
    QObject::connect(saveAct, &QAction::triggered, &p, &MainWindow::save);
    fileMenu->addAction(saveAct);
    fileToolBar->addAction(saveAct);

    const QIcon saveAsIcon = QIcon::fromTheme("document-save-as");
    saveAsAct = new QAction(saveAsIcon, QObject::tr("Save &As..."), &p);
    saveAsAct->setShortcuts(QKeySequence::SaveAs);
    saveAsAct->setStatusTip(QObject::tr("Save the document under a new name"));
    QObject::connect(saveAsAct, &QAction::triggered, &p, &MainWindow::saveAs);
    fileMenu->addAction(saveAsAct);

    fileMenu->addSeparator();

    recentMenu = fileMenu->addMenu(QObject::tr("Recent..."));
    QObject::connect(recentMenu, &QMenu::aboutToShow, &p, &MainWindow::updateRecentFileActions);
    recentFileSubMenuAct = recentMenu->menuAction();

    for (int i = 0; i < MaxRecentFiles; ++i) {
        recentFileActs[i] = recentMenu->addAction(QString(), &p, &MainWindow::openRecentFile);
        recentFileActs[i]->setVisible(false);
    }

    recentFileSeparator = fileMenu->addSeparator();

    p.setRecentFilesVisible(MainWindow::hasRecentFiles());

    fileMenu->addAction(QObject::tr("Switch layout direction"), &p, &MainWindow::switchLayoutDirection);

    fileMenu->addSeparator();

//! [0]
    const QIcon exitIcon = QIcon::fromTheme("application-exit");
    QAction *exitAct = fileMenu->addAction(exitIcon, QObject::tr("E&xit"), qApp, &QApplication::closeAllWindows);
    exitAct->setShortcuts(QKeySequence::Quit);
    exitAct->setStatusTip(QObject::tr("Exit the application"));
    fileMenu->addAction(exitAct);
    //! [0]
}

void MainWindowPrivate::createEditMenuActions_helper()
{
#ifndef QT_NO_CLIPBOARD
    DPTR_P(MainWindow);

    // edit menu
    editMenu = p.menuBar()->addMenu(QObject::tr("&Edit"));
    editToolBar = p.addToolBar(QObject::tr("Edit"));

    const QIcon cutIcon = QIcon::fromTheme("edit-cut", QIcon("./images/cut.png"));
    cutAct = new QAction(cutIcon, QObject::tr("Cu&t"), &p);
    cutAct->setShortcuts(QKeySequence::Cut);
    cutAct->setStatusTip(QObject::tr("Cut the current selection's contents to the "
                            "clipboard"));
    QObject::connect(cutAct, &QAction::triggered, &p, &MainWindow::cut);
    editMenu->addAction(cutAct);
    editToolBar->addAction(cutAct);

    const QIcon copyIcon = QIcon::fromTheme("edit-copy", QIcon("./images/copy.png"));
    copyAct = new QAction(copyIcon, QObject::tr("&Copy"), &p);
    copyAct->setShortcuts(QKeySequence::Copy);
    copyAct->setStatusTip(QObject::tr("Copy the current selection's contents to the "
                             "clipboard"));
    QObject::connect(copyAct, &QAction::triggered, &p, &MainWindow::copy);
    editMenu->addAction(copyAct);
    editToolBar->addAction(copyAct);

    const QIcon pasteIcon = QIcon::fromTheme("edit-paste", QIcon("./images/paste.png"));
    pasteAct = new QAction(pasteIcon, QObject::tr("&Paste"), &p);
    pasteAct->setShortcuts(QKeySequence::Paste);
    pasteAct->setStatusTip(QObject::tr("Paste the clipboard's contents into the current "
                              "selection"));
    QObject::connect(pasteAct, &QAction::triggered, &p, &MainWindow::paste);
    editMenu->addAction(pasteAct);
    editToolBar->addAction(pasteAct);
#endif
}

void MainWindowPrivate::createConnectionMenuActions_helper()
{
    DPTR_P(MainWindow);

    connectionMenu = p.menuBar()->addMenu(QObject::tr("&Connection"));
    uartConfigAct = new QAction(QObject::tr("&UartConfig"), &p);
    uartConfigAct->setStatusTip(QObject::tr("Config the uart port"));

    QObject::connect(uartConfigAct, &QAction::triggered, &p, [=, &p](){
        uartConfigAct->setEnabled(false);
        PageUartConfig *w = new PageUartConfig();
        QObject::connect(w, &PageUartConfig::error, &p, [=, &p](QString str){
            p.statusBar()->showMessage(str, 2000);
        });
//        w->setSerialPort(*port);
        QObject::connect(w, &QWidget::destroyed, [=](){
           uartConfigAct->setEnabled(true);
           w->disconnect();
        });
        mdiArea->addSubWindow(w);
        w->show();
    });
    connectionMenu->addAction(uartConfigAct);
}

void MainWindowPrivate::createToolMenuActions_helper()
{
    DPTR_P(MainWindow);

    toolMenu = p.menuBar()->addMenu(QObject::tr("&Tool"));

    createToolMenuActions_test_helper();

    toolMenu->addSeparator();

    uartAct = new QAction(QObject::tr("U&art"), &p);
    uartAct->setStatusTip(QObject::tr("The uart infomation"));
    QObject::connect(uartAct, &QAction::triggered, &p, [=](){
        uartAct->setEnabled(false);
        PageUart *w = new PageUart();
//        w->setSerialPort(*port);
        QObject::connect(w, &QWidget::destroyed, [=](){
           uartAct->setEnabled(true);
           w->disconnect();
        });
        mdiArea->addSubWindow(w);
        w->show();
    });
    toolMenu->addAction(uartAct);

    createToolMenuActions_hplc_helper();

    createToolMenuActions_electronicscale_helper();

    createToolMenuActions_simplefoc_helper();
}

void MainWindowPrivate::createToolMenuActions_hplc_helper()
{
    DPTR_P(MainWindow);

    toolMenu->addSeparator();

    hplcCommonAct = new QAction(QObject::tr("Hplc &Common Tab Page"), &p);
    hplcCommonAct->setStatusTip(QObject::tr("The Hplc Common Tab Page"));
    QObject::connect(hplcCommonAct, &QAction::triggered, &p, [=](){
        BaseModule *mod = moduleManager->find(ModuleID_HPLC_PumpA);
        if (mod != nullptr)
        {
            hplcCommonAct->setEnabled(false);
            HplcCommonTabPage *w = new HplcCommonTabPage();
            QObject::connect(w, &QWidget::destroyed, [=](){
               hplcCommonAct->setEnabled(true);
               w->disconnect();
            });
            mdiArea->addSubWindow(w);
            w->show();
        }
    });
    toolMenu->addAction(hplcCommonAct);

    hplcDebugInfoAct = new QAction(QObject::tr("Hplc Debug Info Page"), &p);
    hplcDebugInfoAct->setStatusTip(QObject::tr("The Hplc Debug Info Page"));
    QObject::connect(hplcDebugInfoAct, &QAction::triggered, &p, [=, &p](){
        BaseModule *mod = moduleManager->find(ModuleID_HPLC_PumpA);
        if (mod != nullptr)
        {
            hplcDebugInfoAct->setEnabled(false);
            HplcDebugInfoPage *w = new HplcDebugInfoPage();
            QObject::connect(w, &QWidget::destroyed, &p, [=](){
                qDebug() << "debug info page destroy";
               hplcDebugInfoAct->setEnabled(true);
               w->disconnect();
            });
            mdiArea->addSubWindow(w);
            w->show();
        }
    });
    toolMenu->addAction(hplcDebugInfoAct);

    hplcPumpAct = new QAction(QObject::tr("Hplc &Pump Tab Page"), &p);
    hplcPumpAct->setStatusTip(QObject::tr("The Hplc Pump Tab Page"));
    QObject::connect(hplcPumpAct, &QAction::triggered, &p, [=](){
        BaseModule *mod = moduleManager->find(ModuleID_HPLC_PumpA);
        if (mod != nullptr)
        {
            hplcPumpAct->setEnabled(false);
            HplcPumpTabPage *w = new HplcPumpTabPage();
            QObject::connect(w, &QWidget::destroyed, [=](){
               hplcPumpAct->setEnabled(true);
               w->disconnect();
            });
            mdiArea->addSubWindow(w);
            w->show();
        }
    });
    toolMenu->addAction(hplcPumpAct);

    hplcPumpPanelAct = new QAction(QObject::tr("Hplc Pump Panel Page"), &p);
    hplcPumpPanelAct->setStatusTip(QObject::tr("The Hplc Pump Panel Page"));
    QObject::connect(hplcPumpPanelAct, &QAction::triggered, &p, [=, &p](){
        BaseModule *mod = moduleManager->find(ModuleID_HPLC_PumpA);
        if (mod != nullptr)
        {
            hplcPumpPanelAct->setEnabled(false);
            HplcPumpPanel *w = new HplcPumpPanel();
            QObject::connect(w, &QWidget::destroyed, &p, [&](QObject *wid){
                qDebug() << "pump panel page destroy";
               hplcPumpPanelAct->setEnabled(true);
               w->disconnect();
            });
            mdiArea->addSubWindow(w);
            w->show();
        }
    });
    toolMenu->addAction(hplcPumpPanelAct);

    hplcTimeProgramAct = new QAction(QObject::tr("Hplc Time Program Page"), &p);
    hplcTimeProgramAct->setStatusTip(QObject::tr("The Hplc Time Program Page"));
    QObject::connect(hplcTimeProgramAct, &QAction::triggered, &p, [=](){
        BaseModule *mod = moduleManager->find(ModuleID_HPLC_TimeProgram);
        if (mod == nullptr)
            return;

        {
            hplcTimeProgramAct->setEnabled(false);
            HplcTimeProgramPage *w = new HplcTimeProgramPage();
            QObject::connect(w, &QWidget::destroyed, [=](){
               hplcTimeProgramAct->setEnabled(true);
               w->disconnect();
            });
            mdiArea->addSubWindow(w);
            w->show();
        }
    });
    toolMenu->addAction(hplcTimeProgramAct);

    hplcAutoSamplerAct = new QAction(QObject::tr("Hplc AutoSampler Page"), &p);
    hplcAutoSamplerAct->setStatusTip(QObject::tr("The Hplc AutoSampler Page"));
    QObject::connect(hplcAutoSamplerAct, &QAction::triggered, &p, [=](){
        BaseModule *mod = moduleManager->find(ModuleID_HPLC_AutoSampler);
        if (mod != nullptr)
        {
            hplcAutoSamplerAct->setEnabled(false);
            HplcAutoSamplerBasicControlPage *w = new HplcAutoSamplerBasicControlPage(ModuleID_HPLC_AutoSampler);
            QObject::connect(w, &QWidget::destroyed, [=](){
               hplcAutoSamplerAct->setEnabled(true);
               w->disconnect();
            });
            mdiArea->addSubWindow(w);
            w->show();
        }
    });
    toolMenu->addAction(hplcAutoSamplerAct);

    hplcAutoSamplerDeviceAct = new QAction(QObject::tr("Hplc AutoSampler Device Page"), &p);
    hplcAutoSamplerDeviceAct->setStatusTip(QObject::tr("The Hplc AutoSampler Device Page"));
    QObject::connect(hplcAutoSamplerDeviceAct, &QAction::triggered, &p, [=](){
        BaseModule *mod = moduleManager->find(ModuleID_HPLC_AutoSampler_Device);
        if (mod != nullptr)
        {
            hplcAutoSamplerDeviceAct->setEnabled(false);
            HplcAutoSamplerBasicControlDevicePage *w = new HplcAutoSamplerBasicControlDevicePage(ModuleID_HPLC_AutoSampler_Device);
            w->setWindowTitle(QObject::tr("Debug"));
            QObject::connect(w, &QWidget::destroyed, [=](){
               hplcAutoSamplerDeviceAct->setEnabled(true);
               w->disconnect();
            });
            mdiArea->addSubWindow(w);
            w->show();
        }
    });
    toolMenu->addAction(hplcAutoSamplerDeviceAct);
}

void MainWindowPrivate::createToolMenuActions_electronicscale_helper()
{
    DPTR_P(MainWindow);

    toolMenu->addSeparator();

    electronicScaleWeightCurveAct = new QAction(QObject::tr("ElectronicScale Weight Curve Page"), &p);
    electronicScaleWeightCurveAct->setStatusTip(QObject::tr("The ElectronicScale Weight Curve Page"));
    QObject::connect(electronicScaleWeightCurveAct, &QAction::triggered, &p, [=, &p](){
        BaseModule *mod = moduleManager->find(ModuleID_ElectronicScale_LiChen);
        if (mod != nullptr)
        {
            electronicScaleWeightCurveAct->setEnabled(false);
            ElectronicScaleRealTimeCurvePage *w = new ElectronicScaleRealTimeCurvePage();
            QObject::connect(w, &QWidget::destroyed, &p, [=](){
                qDebug() << "close-----------";
               electronicScaleWeightCurveAct->setEnabled(true);
               w->disconnect();
            });
            mdiArea->addSubWindow(w);
            w->show();
        }
    });
    toolMenu->addAction(electronicScaleWeightCurveAct);

    electronicScaleIntervalRateCurveAct = new QAction(QObject::tr("ElectronicScale IntervalRate Curve Page"), &p);
    electronicScaleIntervalRateCurveAct->setStatusTip(QObject::tr("The ElectronicScale IntervalRate Curve Page"));
    QObject::connect(electronicScaleIntervalRateCurveAct, &QAction::triggered, &p, [=, &p](){
        BaseModule *mod = moduleManager->find(ModuleID_ElectronicScale_LiChen);
        if (mod != nullptr)
        {
            electronicScaleIntervalRateCurveAct->setEnabled(false);
            ElectronicScaleDataProcessPage *w = new ElectronicScaleDataProcessPage();
            QObject::connect(w, &QWidget::destroyed, &p, [=](){
               electronicScaleIntervalRateCurveAct->setEnabled(true);
               w->disconnect();
            });
            mdiArea->addSubWindow(w);
            w->show();
        }
    });
    toolMenu->addAction(electronicScaleIntervalRateCurveAct);
}

void MainWindowPrivate::createToolMenuActions_simplefoc_helper()
{
    DPTR_P(MainWindow);

    toolMenu->addSeparator();

    curveAct = new QAction(QObject::tr("Simple FOC Curve"), &p);
    curveAct->setStatusTip(QObject::tr("Show the Simple FOC Curve"));
    QObject::connect(curveAct, &QAction::triggered, &p, [=](){
        SimpleFOCController *module = static_cast<SimpleFOCController*>(moduleManager->find(ModuleID_SimpleFOCController));
        if (module != nullptr)
        {
            SimpleFOCProtocol *protocol = static_cast<SimpleFOCProtocol*>(module->getProtocol());
            BasePort *port = module->getPort();
            if (protocol != nullptr && port != nullptr)
            {
                curveAct->setEnabled(false);
                Curve *w = new Curve();
                w->setTitle("Plot");
                w->setXAxisName(QObject::tr("time(x50ms)"));
                w->addGraph(QObject::tr("raw"), QColor(Qt::red));
                w->addGraph(QObject::tr("calibrated"), QColor(Qt::green));
                w->setWindowTitle(QObject::tr("curve"));
                w->show();

                auto fn = [=](int id, float data, float data2)->void{
                    w->onAddGraphData(2, data, data2);
                };

                QObject::connect(protocol, &SimpleFOCProtocol::addGraphData, w, fn, Qt::QueuedConnection);
    //            QObject::connect(w, &Curve::write, port, &BasePort::onSend, Qt::QueuedConnection);
                QObject::connect(w, &QWidget::destroyed, [=](){
                   uartAct->setEnabled(true);
                   w->disconnect();
                });
                mdiArea->addSubWindow(w);
                w->show();
            }
        }
    });
    toolMenu->addAction(curveAct);
}

void MainWindowPrivate::createToolMenuActions_test_helper()
{
    DPTR_P(MainWindow);
    // test
    testAct = new QAction(QObject::tr("Test"), &p);
    testAct->setStatusTip(QObject::tr("The test page"));
    QObject::connect(testAct, &QAction::triggered, &p, [=](){
        DPTR_P(MainWindow);
        testAct->setEnabled(false);
        TestPage *w = new TestPage();
        QObject::connect(w, &QWidget::destroyed, &p, [=](){
           testAct->setEnabled(true);
           w->disconnect();
        });
        mdiArea->addSubWindow(w);
        w->show();
    });
    toolMenu->addAction(testAct);

    // curve test
    curveTestAct = new QAction(QObject::tr("CurveTest"), &p);
    curveTestAct->setStatusTip(QObject::tr("The curve test page"));
    QObject::connect(curveTestAct, &QAction::triggered, &p, [=](){
        DPTR_P(MainWindow);
        curveTestAct->setEnabled(false);
        CurveTestPage *w = new CurveTestPage();
        QObject::connect(w, &QWidget::destroyed, &p, [=](){
           curveTestAct->setEnabled(true);
           w->disconnect();
        });
        mdiArea->addSubWindow(w);
        w->show();
    });
    toolMenu->addAction(curveTestAct);

    // fft test
    fftTestAct = new QAction(QObject::tr("FFTTest"), &p);
    fftTestAct->setStatusTip(QObject::tr("The fft test page"));
    QObject::connect(fftTestAct, &QAction::triggered, &p, [=](){
        DPTR_P(MainWindow);
        fftTestAct->setEnabled(false);
        FFTTestPage *w = new FFTTestPage();
        QObject::connect(w, &QWidget::destroyed, &p, [=](){
           fftTestAct->setEnabled(true);
           w->disconnect();
        });
        mdiArea->addSubWindow(w);
        w->show();
    });
    toolMenu->addAction(fftTestAct);

    // sig slot test
    sigSlotTestAct = new QAction(QObject::tr("SigSlotTest"), &p);
    sigSlotTestAct->setStatusTip(QObject::tr("The sig slot test page"));
    QObject::connect(sigSlotTestAct, &QAction::triggered, &p, [=](){
        DPTR_P(MainWindow);
        sigSlotTestAct->setEnabled(false);
        SigSlotTestPage *w = new SigSlotTestPage();
        QObject::connect(w, &QWidget::destroyed, &p, [=](){
           sigSlotTestAct->setEnabled(true);
           w->disconnect();
        });
        mdiArea->addSubWindow(w);
        w->show();
    });
    toolMenu->addAction(sigSlotTestAct);

}

void MainWindowPrivate::createWindowMenuActions_helper()
{
    DPTR_P(MainWindow);

    windowMenu = p.menuBar()->addMenu(QObject::tr("&Window"));
//    QObject::connect(windowMenu, &QMenu::aboutToShow, &p, &MainWindow::updateWindowMenu);
    QObject::connect(windowMenu, &QMenu::triggered, &p, &MainWindow::updateWindowMenu);

    closeAct = new QAction(QObject::tr("Cl&ose"), &p);
    closeAct->setStatusTip(QObject::tr("Close the active window"));
    QObject::connect(closeAct, &QAction::triggered,
            mdiArea, &QMdiArea::closeActiveSubWindow);

    closeAllAct = new QAction(QObject::tr("Close &All"), &p);
    closeAllAct->setStatusTip(QObject::tr("Close all the windows"));
    QObject::connect(closeAllAct, &QAction::triggered, mdiArea, &QMdiArea::closeAllSubWindows);

    tileAct = new QAction(QObject::tr("&Tile"), &p);
    tileAct->setStatusTip(QObject::tr("Tile the windows"));
    QObject::connect(tileAct, &QAction::triggered, mdiArea, &QMdiArea::tileSubWindows);

    cascadeAct = new QAction(QObject::tr("&Cascade"), &p);
    cascadeAct->setStatusTip(QObject::tr("Cascade the windows"));
    QObject::connect(cascadeAct, &QAction::triggered, mdiArea, &QMdiArea::cascadeSubWindows);

    nextAct = new QAction(QObject::tr("Ne&xt"), &p);
    nextAct->setShortcuts(QKeySequence::NextChild);
    nextAct->setStatusTip(QObject::tr("Move the focus to the next window"));
    QObject::connect(nextAct, &QAction::triggered, mdiArea, &QMdiArea::activateNextSubWindow);

    previousAct = new QAction(QObject::tr("Pre&vious"), &p);
    previousAct->setShortcuts(QKeySequence::PreviousChild);
    previousAct->setStatusTip(QObject::tr("Move the focus to the previous "
                                 "window"));
    QObject::connect(previousAct, &QAction::triggered, mdiArea, &QMdiArea::activatePreviousSubWindow);

    windowMenuSeparatorAct = new QAction(&p);
    windowMenuSeparatorAct->setSeparator(true);
}

void MainWindowPrivate::createHelpMenuActions_helper()
{
    DPTR_P(MainWindow);

    helpMenu = p.menuBar()->addMenu(QObject::tr("&Help"));

    updateAct = helpMenu->addAction(QObject::tr("&Update"), &p, [=](){
        updateAct->setEnabled(false);
        UpdatePage *w = new UpdatePage();
        QObject::connect(w, &QWidget::destroyed, [=](){
           updateAct->setEnabled(true);
           w->disconnect();
        });
        mdiArea->addSubWindow(w);
        w->show();
    });
    updateAct->setStatusTip(QObject::tr("Check for update the application"));

    serialPortUpdaterAct = helpMenu->addAction(QObject::tr("SerialPortUpdater"), &p, [=](){
        serialPortUpdaterAct->setEnabled(false);
        ui_ymodem *w = new ui_ymodem();
        QObject::connect(w, &QWidget::destroyed, [=](){
           serialPortUpdaterAct->setEnabled(true);
           w->disconnect();
        });
        mdiArea->addSubWindow(w);
        w->show();
    });
    serialPortUpdaterAct->setStatusTip(QObject::tr("Update device firmware with serial port"));

    aboutAct = helpMenu->addAction(QObject::tr("&About"), &p, &MainWindow::about);
    aboutAct->setStatusTip(QObject::tr("Show the application's About box"));
}
